﻿#include "FingerprintReader.h"
#include "FingerprintCacheDB.h"
#include "ZKFingerReader/libs/include/libzkfp.h"
#include <QDebug>
namespace ZKFP
{

static const int ZKFP_IMAGE_WIDTH_RO = 1;
static const int ZKFP_IMAGE_HEIGHT_RO = 2;
static const int ZKFP_IMAGE_DPI_RW = 3;
static const int ZKFP_IMAGE_SIZE_RO = 106;
static const int ZKFP_VID_PID_RO = 1015;
static const int ZKFP_FAKE_ON_RW = 2002;
static const int ZKFP_REAL_FINGER_RO = 2004;
static const int ZKFP_VENDOR_NAME_RO = 1101;
static const int ZKFP_PRODUCT_NAME = 1102;
static const int ZKFP_SERIAL_NUNBER = 1103;

//static const int MAX_TEMPLATE_SIZE = 2048;
static const int ZKFP_ERR_OK = 0;

int autoInitCount = 0;
static bool autoInit()
{
    if(autoInitCount == 0)
    {
        if( ZKFPM_Init() == 0)
        {
            autoInitCount ++;
            return true;
        }
        else
        {
            return false;
        }
    }
    return true;
}

static bool autoTerminate()
{
    autoInitCount --;
    if(autoInitCount == 0)
    {
        return (ZKFPM_Terminate() == 0);
    }
    return false;
}


FingerprintReader::FingerprintReader(QObject *parent)
    : QThread(parent),
      m_init(false),
      m_handle(0),
      m_image_height(0),
      m_image_width(0),
      m_image_size(0),
      m_vendorName(""),
      m_productName(""),
      m_serialNumber(""),
      m_stop(true)
{
    m_init = autoInit();
    qDebug() << "autoInit = " << m_init;
}

int FingerprintReader::getDeviceCount()
{
    return ZKFPM_GetDeviceCount();
}

bool FingerprintReader::openDevice(int index)
{
    m_handle = ZKFPM_OpenDevice(index);
    if(m_handle != 0)
    {
        setFakeFunc(true);

        unsigned int length = sizeof(int);

        m_image_DPI = 500;
        length = sizeof(int);
        ZKFPM_SetParameters(m_handle, ZKFP_IMAGE_DPI_RW, reinterpret_cast<unsigned char *> (&m_image_DPI), length);
        length = sizeof(int);
        ZKFPM_GetParameters(m_handle, ZKFP_IMAGE_DPI_RW, reinterpret_cast<unsigned char *> (&m_image_DPI), &length);

        ZKFPM_GetParameters(m_handle, ZKFP_IMAGE_WIDTH_RO, reinterpret_cast<unsigned char *> (&m_image_width), &length);
        length = sizeof(int);
        ZKFPM_GetParameters(m_handle, ZKFP_IMAGE_HEIGHT_RO, reinterpret_cast<unsigned char *> (&m_image_height), &length);
        length = sizeof(int);
        ZKFPM_GetParameters(m_handle, ZKFP_IMAGE_SIZE_RO, reinterpret_cast<unsigned char *> (&m_image_size), &length);

        qDebug() << "image width = " << m_image_width << ", height = " << m_image_height << ", DPI = " << m_image_DPI;

        char name[128] = {0};
        memset(name, 0, 128);
        length = 128;
        ZKFPM_GetParameters(m_handle, ZKFP_VENDOR_NAME_RO, reinterpret_cast<unsigned char *>(name), &length);
        m_vendorName.clear();
        m_vendorName.append(name);

        memset(name, 0, 128);
        length = 128;
        ZKFPM_GetParameters(m_handle, ZKFP_PRODUCT_NAME, reinterpret_cast<unsigned char *>(name), &length);
        m_productName.clear();
        m_productName.append(name);

        memset(name, 0, 128);
        length = 128;
        ZKFPM_GetParameters(m_handle, ZKFP_SERIAL_NUNBER, reinterpret_cast<unsigned char *>(name), &length);
        m_serialNumber.clear();
        m_serialNumber.append(name);

        qDebug() << "Vendor Name = " << m_vendorName;
        qDebug() << "Product Name = " << m_productName;
        qDebug() << "Serial Number = " << m_serialNumber;

        uint16_t vid_pid[2] = {0, 0};
        length = 4;
        ZKFPM_GetParameters(m_handle, ZKFP_VID_PID_RO, reinterpret_cast<unsigned char *>(vid_pid), &length);
        m_vid = vid_pid[0];
        m_pid = vid_pid[1];
        qDebug() << "VID = " << m_vid << ", PID = " << m_pid;
        return true;
    }
    else
    {
        m_vendorName.clear();
        m_productName.clear();
        m_serialNumber.clear();
        m_vid = 0;
        m_pid = 0;
    }
    return false;
}

bool FingerprintReader::isFakeFuncOn()
{
    m_isFakeOn = 0;
    unsigned int length = sizeof(m_isFakeOn);
    ZKFPM_GetParameters(m_handle, ZKFP_FAKE_ON_RW, reinterpret_cast<unsigned char *>(&m_isFakeOn), &length);
    return m_isFakeOn;
}

void FingerprintReader::setFakeFunc(bool on)
{
    int fakeON = on ? 1 : 0;
    unsigned int length = sizeof(m_isFakeOn);
    ZKFPM_SetParameters(m_handle, ZKFP_FAKE_ON_RW, reinterpret_cast<unsigned char *> (&fakeON), sizeof(int));
    ZKFPM_GetParameters(m_handle, ZKFP_FAKE_ON_RW, reinterpret_cast<unsigned char *>(&m_isFakeOn), &length);
}

void FingerprintReader::closeDevice()
{
    if(isRunning())
    {
        cancelCapture();
    }
    if(m_handle)
    {
        ZKFPM_CloseDevice(m_handle);
        m_vendorName.clear();
        m_productName.clear();
        m_serialNumber.clear();
        m_image_height = 0;
        m_image_width = 0;
        m_image_size = 0;
        m_vid = 0;
        m_pid = 0;
        m_handle = 0;
    }
}

QImage FingerprintReader::acquireImage()
{
    int width, height;
    uint length = 4;
    ZKFPM_GetParameters(m_handle, 1, (unsigned char*)&width, &length);
    ZKFPM_GetParameters(m_handle, 2, (unsigned char*)&height, &length);
    QImage image(width, height, QImage::Format_Grayscale8);
    ZKFPM_AcquireFingerprintImage(m_handle, image.bits(), width * height);

    return image;
}

QString FingerprintReader::vendorName() const
{
    return m_vendorName;
}

QString FingerprintReader::productName() const
{
    return m_productName;
}

QString FingerprintReader::serialNumber() const
{
    return m_serialNumber;
}

uint16_t FingerprintReader::getVID() const
{
    return m_vid;
}

uint16_t FingerprintReader::getPID() const
{
    return m_pid;
}

bool FingerprintReader::isRealFinger()
{
    int nFakeStatus = 0;
    unsigned int retLen = sizeof(int);
    if (0 == ZKFPM_GetParameters(m_handle, ZKFP_REAL_FINGER_RO, (unsigned char*)&nFakeStatus, &retLen))
    {
        if ((nFakeStatus & 31) == 31)
        {
            return true;
        }
    }
    return false;
}

void FingerprintReader::run()
{
    qDebug() << "Fingerprint sensor thead starting";
    unsigned char * imageBuffer = new unsigned char[m_image_height * m_image_width + 100];
    QImage image(m_image_width, m_image_height, QImage::Format_Grayscale8); //image 要求数据是 32位对齐的。

    unsigned char fpBuffer[MAX_TEMPLATE_SIZE];
    unsigned int tempLen = MAX_TEMPLATE_SIZE;
    while(!m_stop)
    {
        tempLen = MAX_TEMPLATE_SIZE;
        int ret = ZKFPM_AcquireFingerprint(m_handle, imageBuffer, m_image_size, fpBuffer, &tempLen);

        //qDebug() << "AcquireFingerprint = " << ret;
        if (0 == ret)
        {
            qDebug() << "AcquireFingerprint = " << ret;
            qDebug() << "Template size = " << tempLen;
            if ( m_isFakeOn && !isRealFinger() )	//FakeFinger Test
            {
                emit fakeFinger();
                qDebug() << "fakeFinger";
            }
            else
            {
                for(int i = 0; i < m_image_height; i++)
                {
                    unsigned char * to = image.scanLine(i);
                    unsigned char * from  = imageBuffer + i * m_image_width;
                    memcpy(to, from, m_image_width);
                }
                QByteArray pfTemplate(reinterpret_cast<char *>(fpBuffer), tempLen);
                //fpTemplate.truncate(tempLen);
                emit onFingerprintReceived(image, pfTemplate);
                qDebug() << "emit onImageReceived(image, fpTemplate)";

            }
        }
        Sleep(100);
    }
    qDebug() << "Fingerprint sensor thead stoped";
}

void FingerprintReader::beginCapture()
{
    if(m_init && m_handle)
    {
        m_stop = false;
    }
    start();
}

void FingerprintReader::cancelCapture()
{
    m_stop = true;
}

FingerprintReader::~FingerprintReader()
{
    if(m_handle)
    {
        closeDevice();
    }
    autoTerminate();
}


}

